using System.Text.Json;
using FytSoa.Application.Erp.Param;
using FytSoa.Domain.Erp;
using FytSoa.Sugar;
using FytSoa.Common.Utils;
using FytSoa.Common.Param;
using FytSoa.Common.Result;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace FytSoa.Application.Erp;

/// <summary>
/// erp-产品真正库存服务接口
/// </summary>
[ApiExplorerSettings(GroupName = "v9")]
public class ErpProductStockService : IApplicationService 
{
    private readonly SugarRepository<ErpProductStock> _thisRepository;
    public ErpProductStockService(SugarRepository<ErpProductStock> thisRepository)
    {
        _thisRepository = thisRepository;
    }
    
    /// <summary>
    /// 查询所有——分页
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<PageResult<ErpProductStockInfoDto>> GetPagesAsync(ErpProductStockSearchParam param)
    {
        var query = await _thisRepository.AsQueryable()
            .WhereIF(!string.IsNullOrEmpty(param.Key),m=>
                SqlFunc.Subqueryable<ErpProduct>().Where(s => s.Id == m.ProductId && s.Name.Contains(param.Key)).Any())
            .WhereIF(!string.IsNullOrEmpty(param.TypeId),m=>
                SqlFunc.Subqueryable<ErpProduct>().Where(s => s.Id == m.ProductId && s.TypeId==long.Parse(param.TypeId)).Any())
            .WhereIF(!string.IsNullOrEmpty(param.WarehouseId),m=>
                SqlFunc.Subqueryable<ErpInstockProduct>().Where(s => s.ProductId == m.ProductId && 
                                                                     s.WarehouseId==long.Parse(param.WarehouseId)).Any())
            .OrderByDescending(m=>m.Id)
            .ToPageAsync(param.Page, param.Limit);
        var result=query.Adapt<PageResult<ErpProductStockDto>>();
        //根据产品编号查询产品具体信息
        var resultProduct = new List<ErpProductStockInfoDto>();
        if (result.Items.Count>0) 
        {
            var productRepository = _thisRepository.ChangeRepository<SugarRepository<ErpProduct>>();
            var productIds = result.Items.Select(m => m.ProductId).ToList();
            var productList = await productRepository.AsQueryable()
                .Where(m => productIds.Contains(m.Id))
                .Includes(m=>m.Type)
                .Includes(m=>m.Unit)
                .Includes(m=>m.Supplier)
                .ToListAsync();
            resultProduct =productList.Adapt<List<ErpProductStockInfoDto>>();
            
            //查询仓库信息
            var instockProductRepository = _thisRepository.ChangeRepository<SugarRepository<ErpInstockProduct>>();
            var instockWarehouse = await instockProductRepository.AsQueryable()
                .Where(m => productIds.Contains(m.ProductId))
                .GroupBy(m => new { m.ProductId, m.WarehouseId })
                .Select(m => new ErpProductStockInfoDto.ProductWarehouse()
                {
                    Id = m.WarehouseId,
                    ProductId = m.ProductId,
                    Count = SqlFunc.AggregateSum(m.Count),
                })
                .ToListAsync();
            if (instockWarehouse.Count > 0)
            {
                var warehouseRepository = _thisRepository.ChangeRepository<SugarRepository<ErpWarehouse>>();
                var warehouseIds = instockWarehouse.Select(m => m.Id).Distinct().ToList();
                var warehouseList = await warehouseRepository.GetListAsync(m => warehouseIds.Contains(m.Id));
                foreach (var item in instockWarehouse)
                {
                    item.Name = warehouseList.FirstOrDefault(m => m.Id == item.Id)!.Name;
                }
            }
            foreach (var item in resultProduct)
            {
                item.Count = result.Items.FirstOrDefault(m => m.ProductId == item.Id)!.Count;
                item.Warehouse = instockWarehouse.Where(m => m.ProductId == item.Id).ToList();
            }
        }
        return new PageResult<ErpProductStockInfoDto>()
        {
            TotalItems = result.TotalItems,
            TotalPages = result.TotalPages,
            Items = resultProduct
        };
    }

    /// <summary>
    /// 根据主键查询
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public async Task<ErpProductStockDto> GetAsync(long id)
    {
        var model = await _thisRepository.GetByIdAsync(id);
        return model.Adapt<ErpProductStockDto>();
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task AddAsync(List<ErpProductStock> param)
    {
        var productIds = param.Select(m => m.ProductId).ToList();
        var addList = new List<ErpProductStock>();
        var updateList = new List<ErpProductStock>();
        var productList = await _thisRepository.GetListAsync(m => productIds.Contains(m.ProductId));
        foreach (var item in param)
        {
            var product = productList.FirstOrDefault(m => m.ProductId == item.ProductId);
            if (product!=null)
            {
                product.Count += item.Count;
                updateList.Add(product);
            }
            else
            {
                addList.Add(item);
            }
        }
        if (addList.Count>0)
        {
            await _thisRepository.InsertRangeAsync(addList);
        }

        if (updateList.Count>0)
        {
            await _thisRepository.UpdateRangeAsync(updateList);
        }
    }

    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<bool> ModifyAsync(ErpProductStockDto model) =>
        await _thisRepository.UpdateAsync(model.Adapt<ErpProductStock>());

    /// <summary>
    /// 删除,支持批量
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    [HttpDelete]
    public async Task<bool> DeleteAsync([FromBody]List<long> ids) =>
        await _thisRepository.DeleteAsync(m=>ids.Contains(m.Id));
}
